/*****************************************************************************
 * File:        sim_engine.c
 * Description: This file consists primarily of the main() function for the
 *              simulator. The function is basicaly a loop that reads a
 *              transaction and simulates its flow through the cache/memory
 *              hierarchy.
 *
*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <exception>
#include <sys/time.h>

using namespace std;

#include "cache.h"
#include "sim_engine.h"
#include "transaction.h"
#include "processor.h"
#include "pepsi_init.h"
#include "pepsi_stats.h"
#include "sharedglobals.h"
#include "nox/router.h"
#include "nox/shared.h"
#include "nox/batch.h"
#include "nox/rank.h"


#define MAX_POOL_SIZE 100000



class memory_obj_t
{
public:
    ///8. Memory transaction
    void read_complete(unsigned, uint64_t, uint64_t);
    void write_complete(unsigned, uint64_t, uint64_t);
};
memory_obj_t memory_obj;

/* FIXME: this may be broken, currently */
void power_callback(double a, double b, double c, double d)
{
    //printf("power callback: %0.3f, %0.3f, %0.3f, %0.3f\n",a,b,c,d);
}


/* DRAM callback functors */
void memory_obj_t::read_complete(unsigned id, uint64_t address, uint64_t clock_cycle)
{
    //printf("[Callback] read complete: %d 0x%lx cycle=%lu\n", id, address, clock_cycle);
    int max_tr_time = 0;

    for(int index = 0; index < tr_pool.size(); index++)
    {
        TRANSTYPE *temp_tr;
        temp_tr = &(tr_pool.at(index));
        if(temp_tr->address == address && temp_tr->memq_enter  != 0)
            //if(temp_tr->timestamp > max_tr_time)
        {

            temp_tr->timestamp = global_clock;
            temp_tr->mem_queue_wait += global_clock - temp_tr->memq_enter;
            //===============
            temp_tr = NULL;
            break;
            //===================
            max_tr_time = temp_tr->timestamp;
            //printf("\n READ_COMPLETE: trid: %d  :: Data Return time : %d", temp_tr->tr_id, global_clock);
        }
    }
}

void memory_obj_t::write_complete(unsigned id, uint64_t address, uint64_t clock_cycle)
{
    //printf("[Callback] write complete: %d 0x%lx cycle=%lu\n", id, address, clock_cycle);

    for(int index = 0; index < tr_pool.size(); index++)
    {
        TRANSTYPE *temp_tr;
        temp_tr = &(tr_pool.at(index));
        if(temp_tr->address == address && temp_tr->memq_enter  != 0)
        {
            temp_tr->timestamp = global_clock;
            temp_tr->mem_queue_wait += global_clock - temp_tr->memq_enter;
            //printf("\n WRITE_COMPLETE: trid: %d  :: Data Return time : %d", temp_tr->tr_id, global_clock);
            temp_tr = NULL;
            break;
        }
    }
}



int main(int argc, char *argv[])
{
    char cmp_conf_file[200] = "cmp-conf.file";
    char nox_conf_file[200] = "nox-conf.file";
    char trace_conf_file[200] = "trace-conf.file";

    int instruction_passes=0;
    int max_passes=30;

    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    //profile runs just analyzing memory reference streams
    //set profile run to true
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    profile_run=false;
    if(profile_run)
    {
        numcpus = atoi(argv[1]);
        strcpy(benchmark,argv[2]);
        trace_setup(trace_conf_file,benchmark,0,numcpus);
        for(int i = 0; i < numcpus; i++)
            //#proc number, trace file name, reorder buffer size, issue width, commit
            //width, execution width
            processor[i].initProcessor(mp_trace_file_name[i],i,256,4,4,4);

        while(finished_processors[0] < numcpus)
        {

            if(!(processor[0].instructions%10000))
                printf("************Summary  %lld**************\n",processor[0].instructions);
            for(int i = 0; i < numcpus; i++)
                if(!processor[i].profile())
                    finished_processors[0]++;
            //profile_stats();
        }
        profile_stats();
        print_table();

        exit(1);
    }
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    // start simulations (argument parsing)
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/

    int active_cpus=0;
    if(argc == 1)
        printf("usage <benchmark> <#processors> <cmp-conf.file> <nox-conf.file> <-page-interleaving(optional)>\n");

    //benchmark based
    if(argc >= 2)
        strcpy(benchmark,argv[1]);

    if(argc >= 3)
        active_cpus = atoi(argv[2]);

    if(argc >= 4)
        strcpy(cmp_conf_file,argv[3]);

    if(argc >= 5)
        strcpy(nox_conf_file,argv[4]);

    if(argc >= 6)
    {
        if(!strcmp(argv[5],"-page-interleaving"))
            bank_map = MEM_PAGE_INTERLEAVING;
    }

    sim_setup(cmp_conf_file);
    if(strstr(benchmark,"mpmix"))
    {
        char buff[20];
        FILE *fp = fopen(benchmark, "r");
        int numProcs = 0;
        int StartProc = 0, EndProc = 0;

        printf("Setting up for mpmix\n");

        while (fgets(buff, 80, fp))
        {
            if(strstr(buff,"#"))
                continue;
            sscanf(buff,"%s %d\n",benchmark,&numProcs);
            EndProc = StartProc + numProcs;
            trace_setup(trace_conf_file,benchmark,StartProc,EndProc);
            strcpy(buff,"");
            StartProc = EndProc;
        }
    }
    /*else if(active_cpus < numcpus)
  {
    trace_setup(trace_conf_file,benchmark,0,active_cpus);
    strcpy(benchmark,"nop");
    trace_setup(trace_conf_file,benchmark,active_cpus,numcpus);
  }*/
    else if(active_cpus < numcpus)
    {
        printf("Setting up for active_cpus < numcpus\n");
        trace_setup(trace_conf_file,benchmark,active_cpus,active_cpus+1);
        strcpy(benchmark,"nop");
        trace_setup(trace_conf_file,benchmark,0,active_cpus);
        trace_setup(trace_conf_file,benchmark,active_cpus+1,numcpus);
    }
    else
    {
        printf("Setting up for single benchmark\n");
        trace_setup(trace_conf_file,benchmark,0,numcpus);
    }

    if(!SHORT_CIRCUIT)
        nox_setup(nox_conf_file);

    tag_shift = clevel[LLC].cache[0].tag_shift;
    tr_pool.reserve(MAX_TR);

    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    //Initialize processor here and fastforward to simpoint
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    for(int i = 0; i < numcpus; i++)
        //#proc number, trace file name, reorder buffer size, issue width, commit
        //width, execution width
    {
        processor[i].initProcessor(mp_trace_file_name[i],i,64,1,1,1);
        processor[i].fastforward();
    }
    findUniqueApps();



    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    // DRAM Initialize

    if(DRAMSIM_MEMORY)
    {
        DRAMTransactionCompleteCB *read_cb = new Callback<memory_obj_t, void, unsigned, uint64_t, uint64_t>(&memory_obj, &memory_obj_t::read_complete);
        DRAMTransactionCompleteCB *write_cb = new Callback<memory_obj_t, void, unsigned, uint64_t, uint64_t>(&memory_obj, &memory_obj_t::write_complete);

        mem1->RegisterCallbacks(read_cb, write_cb, power_callback);
        mem2->RegisterCallbacks(read_cb, write_cb, power_callback);
        mem3->RegisterCallbacks(read_cb, write_cb, power_callback);
        mem4->RegisterCallbacks(read_cb, write_cb, power_callback);
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    }


    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    //network tracer to produce condensed traces or profile run to anaylze network load
    //traffic pattern etc
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    //for(int i = 0; i < numcpus; i++)
    //processor[i].NetworkTracer(30*MILLION, 0);
    //exit(1);

    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    //statistics interval
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/

    instructions_to_simulate = MILLION/100; //100
    clear_stats_at_pass = 3;
    max_passes = 300; //300; //500;
    global_clock=0;
    instruction_passes=0;
    if(strstr(mp_trace_file_name[0],"pattern"))
        max_passes = 15;
    ResetPerNodeBuffOccupany();

    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    //START SIMULATION ENGINE
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    while(!pepsi_end)
    {

        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        //1. Simulate Processors
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        for(int i = 0; i < numcpus; i++)
            processor[i].doCycle();
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        //2. Simulate Caches and Memory
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        simulate_memory();


        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        //3. Simulate Interconnect
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        if(!SHORT_CIRCUIT)
        {
            if(csim_inj_msgs != num_ejt_msg)
                nox_sim((global_clock + 1)*CLOCK_FREQ_SCALE);
            else
                sim_clock = (global_clock + 1)*CLOCK_FREQ_SCALE;
        }
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        //Monitor System State for fairness throttling etc
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        /*if(!(global_clock%BUFF_OCCUPANCY_INTERVAL))
        {
          UpdatePerClassBuffOccupancy();
          UpdatePerNodeBuffOccupancy();
        }

        if(ARB_TYPE == PR && age_based_arbitration == false)
        {
          if(!(global_clock%MONITOR_INTERVAL_LENGTH))
            monitorUnfairness();
        }*/

        if(GlobalBatchMode > BATCHING_MODE_GLOBAL)
        {
            //printf("%lld %d\n",global_clock,GlobalCurrentBatchId);
            UpdateBatchCounter();
            UpdateBatchId();
            UpdateOldestBatch();
        }
        if(GlobalRankMode > RANKING_GLOBAL)
            GetRankMetricValues();


        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        //4. DRAM  Clock Update
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        if(DRAMSIM_MEMORY)
        {
            mem1->update();
            mem2->update();
            mem3->update();
            mem4->update();
        }
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        //5. Update system clock
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        global_clock++;
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/

        //if(!(global_clock%50000))
        //getInstProgress();

        /*if(batching_mode[0] == BATCHING_GLOBAL_TIMEBASED)
        {
          if(num_inj_msg)
            if(CountBatchFlits(OldestCompleteBatch%MAX_BATCH_ID) == 0)
            {
              printf("\n\n*********************************************\n");
              printf("Oldest Batch Update %lld NextBatchID %lld @clock %lld LastBatchId:%lld\n",OldestCompleteBatch, (OldestCompleteBatch+1)%MAX_BATCH_ID, sim_clock, last_batch_id[0]);
              printf("*********************************************\n\n");
              OldestCompleteBatch++;
            }

          //for(int i=0; i<MAX_BATCH_ID; i++)
          //p = CountBatchFlits(i)
        }*/


        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        //Upadate Complete
        /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
        if(DEBUG)
            dump_state();

        if(finished_processors[instruction_passes] == numcpus)
        {
            /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
            //5. Statistics per million instructions of each processor
            /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
            //ASIT:Uncomment below
            //for(int i = 0; i < numcpus; i++)
            //  processor[i].printOracleStats(instruction_passes%max_passes, max_passes);
            //ASIT: end comment

            //////Single App Profile Starts
            //for(int i = 0; i < numcpus; i++)
            //  processor[i].printCumulativeStats(instruction_passes%MAX_PASS);
            //////Single App Profile Ends

            //getIPCMatrix(instruction_passes%MAX_PASS);
            //getStallMatrix(instruction_passes%MAX_PASS);
            //getNetworkStatsMatrix(instruction_passes%MAX_PASS);
            //getAppStats(instruction_passes%MAX_PASS);

            printf("************Summary for Pass %.3lfMillion instructions **************\n",(double)((instruction_passes+1)*instructions_to_simulate)/1000000.0);

            for(int i = 0; i < numcpus; i++)
                processor[i].getStats(instruction_passes);

            if(!SHORT_CIRCUIT)
            {
                //Commented by Nachi
                //for(int i = 0; i < numcpus; i++)
                // processor[i].getNetworkStats(instruction_passes);
            }
            else
                printf("injection rate:%.2lf\n",100*(csim_inj_msgs/((double)(numcpus + num_llc_banks)*global_clock)));

            //Network stats
            if(!SHORT_CIRCUIT)
                sim_result();
            //Cache Stats
            print_stats();

            getAvgStats(instruction_passes);

            //mem1->printStats(false);
            // mem2->printStats(false);
            // mem3->printStats(false);
            // mem4->printStats(false);

            printf("************Summary for Pass %.3lfM instructions **************\n",(double)((instruction_passes+1)*instructions_to_simulate)/1000000.0);

            /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
            //7. Simulation End Condition
            /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
            if(instruction_passes == max_passes)
                pepsi_end=true;

            instruction_passes++;

            // if(instruction_passes == clear_stats_at_pass)
            // {
            // clear_stats();
            // printf("\n\n\n\n\n\n\n Cleared Stats!! ");
            // }
        }

    }

    //if(STAT)
    {
        // print_data_sharing();
        print_stats();
        //if(!SHORT_CIRCUIT)
        //sim_result();

    }

    if(DRAMSIM_MEMORY)
    {
        mem1->printStats(true);
        mem2->printStats(true);
        mem3->printStats(true);
        mem4->printStats(true);
    }

    killcachesim();

    // Prompt before exiting for debug
    //if(!INTERACTIVE && DEBUG && PRINT)
    //  getchar();

    if(RECORD_NOC)
        gzclose(rec_noc_fp);

    if(RECORD)
        gzclose(out_fp);

    printf("All done!!! Happily Exiting :)\n");
    return 0;
}

void simulate_memory()
{
    static long long blocked_iter=0;
    bool blocked = true;
    long long id=0;
    TRANSTYPE *temp_tr;
    vector<TRANSTYPE>::iterator temp;

    num_mem_req_served = 0; //this cycle.

    if(tr_pool.size() == 0)
        return;

    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    // Process each memory transaction
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    for(int index = 0; index < tr_pool.size(); index++)
    {
        try
        {temp_tr = &(tr_pool.at(index));}
        catch(std::exception e)
        {if(DEBUG) printf(" The location at %d is empty in tr_pool, Exception %s", index, e.what());}

        id = temp_tr->tr_id;

        if(temp_tr->state == EXIT && temp_tr->timestamp <= global_clock)
        {
            determine_new_tr_event(temp_tr);
            //Debug
            /*if(id==1256)
        {print_tr(1256);
         exit(1);
        }*/
            temp_tr = map_transaction(id);
            if(temp_tr->mem_op_id != -1)
                processor[temp_tr->tid].setReady(temp_tr->rob_entry,temp_tr->tr_id);

            for(temp = tr_pool.begin(); temp != tr_pool.end(); temp++)
                if(temp->tr_id == id)
                {tr_pool.erase(temp); break;}
            index--;
            continue;
        }

        if(temp_tr->timestamp <= global_clock )
        {
            determine_new_tr_event(temp_tr);
            temp_tr = map_transaction(id);
        }
        if(temp_tr->timestamp != BLOCKED)
        {
            blocked = false;
            blocked_iter = 0;
        }
    }//for

    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
    // Check live lock
    /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/

    if(blocked)
        blocked_iter++;

    if(blocked_iter > 5000)
    {
        blocked_iter = 0;
        char c;
        printf("FATAL ERR SIMULATION IN LIVELOCK !!!!\n");
        DEBUG=1;
        PRINT=1;
        INTERACTIVE=0;
        verbose = 0;
        if(!SHORT_CIRCUIT && csim_inj_msgs > num_ejt_msg)
            printf("Possible network deadlock csim:%lld nox ejt:%lld nox inj:%lld\n",csim_inj_msgs,num_ejt_msg, num_inj_msg);
        printf("Changing to debug mode (y/n) ?\n");
        dump_state();
        print_llc_transactions();
        //  c = getchar();
        //  if(c=='n')
        exit(1);
    }

    return;

}


void dump_state()
{
    printf("\n********************SYSTEM STATE AT TIME <%lld>****************\n",global_clock);
    if(PRINT )
    {
        printf("TRANSACTION POOL\n");
        print_pool();
        printf("MLC Queues\n");
        print_mlc();
        printf("LLC Queues\n");
        print_llc();
        printf("MEMORY Queue\n");
        print_mem();
        printf("\n*****************SYSTEM STATE AT TIME <%lld>***************\n",global_clock);
        if(INTERACTIVE)
            getchar();

    }
    printf("*********************POOL SIZE <%d>*********************\n",tr_pool.size());

}

bool mlc_transfer_overflow(int cpuid)
{
    int size = clevel[MLC].cache[cpuid].queue.size();
    // printf("size old %d for MLC%d\n", size, cpuid);
    if(size >= cache_rq_size[MLC])
        return true;

    std::vector<TRANSTYPE>::iterator tr;
    for(tr = tr_pool.begin(); tr != tr_pool.end() ; tr++)
        if(tr->cpuid == cpuid && tr->state == MLC_BUS_TRANSFER)
            size++;
    clevel[MLC].cache[cpuid].tot_rq_size += size;
    clevel[MLC].cache[cpuid].rq_size_samples++;
    //printf("size new %d\n", size);
    if(size < cache_rq_size[MLC])
        return false;
    else
        return true;
}


void clear_stats()
{

    for(int i=0; i< numcpus; i++)
    {
        processor[i].Reset();
    }

    for(int i=0; i< numcpus; i++)
    {
        processor[i].instructions=0;
        // processor[i].sum_rob_occupancy
        // processor[i].l1misses
        // processor[i].l2misses
        // processor[i].memory_stall_cycles
        // processor[i].memory_instructions
        // processor[i].bank_spread_counter
        // processor[i].bank_spread
        // processor[i].network_stall_cycles
        // processor[i].packets-processor[i].local_packets
        // processor[i].hop_count

    }

    total_icn_latency = 0;
    total_icn_msgs=0;
    reads=0;
    writes=0;
    mlc_hits=0;
    mlc_misses=0;
    conflict_pri_misses=0;
    total_resp_time=0;
    llc_hits=0;
    llc_misses=0;
    for(int i = 0; i<128;i++)
    {
        misses_per_core[i] = 0;
        commit_refs[i]= 0;
        refs[i] = 0;
        core_prefetch_initiated[i]=0;
        core_relative_prefetch_initiated[i]=0;
        core_prefetch_hits[i]=0;
        core_prefetch_accuracy[i]=0;
        core_prefetch_coverage[i]=0;
        core_l2mpki[i]=0;
    }
    csim_inj_msgs=0;
    total_csim_nic_qdelay=0;
    addr_msgs=0;
    data_msgs=0;
    wb_msgs=0;
    snoop_msgs=0;
    // insts_executed=0;


    pf_hits_vector.clear();
    total_prefetch_initiated=0;
    total_prefetch_hits=0;
    total_prefetch_cancelled=0;
    total_prefetch_late=0;

    //global_clock=0;
    numrefs_for_repl=0;
}
